package com.gu.domain.utils;


import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import javax.crypto.SecretKey;
import java.util.Date;
import java.util.UUID;

/**
 * JWT工具类
 * @author 35238
 * @date 2023/7/22 0022 21:18
 */
public class JwtUtil {

    //有效期为
    public static final Long JWT_TTL = 72 * 60 * 60 * 1000L; // 72小时
    //设置秘钥明文 - 需要更长的密钥
    public static final String JWT_KEY = "gu12345678901234567890123456789012"; // 至少32位

    // 使用安全的密钥
    private static final SecretKey SECRET_KEY = Keys.hmacShaKeyFor(JWT_KEY.getBytes());

    public static String getUUID(){
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 生成jtw
     * @param subject token中要存放的数据（json格式）
     * @return
     */
    public static String createJWT(String subject) {
        return getJwtBuilder(subject, null, getUUID()).compact();
    }

    /**
     * 生成jtw
     * @param subject token中要存放的数据（json格式）
     * @param ttlMillis token超时时间
     * @return
     */
    public static String createJWT(String subject, Long ttlMillis) {
        return getJwtBuilder(subject, ttlMillis, getUUID()).compact();
    }

    private static JwtBuilder getJwtBuilder(String subject, Long ttlMillis, String uuid) {
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);

        if (ttlMillis == null) {
            ttlMillis = JwtUtil.JWT_TTL;
        }

        long expMillis = nowMillis + ttlMillis;
        Date expDate = new Date(expMillis);

        return Jwts.builder()
                .setId(uuid)              // 唯一的ID
                .setSubject(subject)      // 主题 可以是JSON数据
                .setIssuer("gu")          // 签发者
                .setIssuedAt(now)         // 签发时间
                .setExpiration(expDate)   // 过期时间
                .signWith(SECRET_KEY);    // 使用安全的签名密钥
    }

    /**
     * 创建token
     * @param id
     * @param subject
     * @param ttlMillis
     * @return
     */
    public static String createJWT(String id, String subject, Long ttlMillis) {
        return getJwtBuilder(subject, ttlMillis, id).compact();
    }

    public static void main(String[] args) {
        try {
            // 测试生成token
            String token = createJWT("testUser");
            System.out.println("生成的Token: " + token);

            // 测试解析token
            Claims claims = parseJWT(token);
            System.out.println("解析的Claims: " + claims);
            System.out.println("Subject: " + claims.getSubject());
            System.out.println("ID: " + claims.getId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析JWT
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseJWT(String jwt) throws Exception {
        return Jwts.parserBuilder()
                .setSigningKey(SECRET_KEY)
                .build()
                .parseClaimsJws(jwt)
                .getBody();
    }

    /**
     * 验证Token是否有效
     * @param token
     * @return
     */
    public static boolean validateToken(String token) {
        try {
            parseJWT(token);
            return true;
        } catch (ExpiredJwtException e) {
            System.out.println("Token已过期: " + e.getMessage());
            return false;
        } catch (UnsupportedJwtException e) {
            System.out.println("不支持的Token格式: " + e.getMessage());
            return false;
        } catch (MalformedJwtException e) {
            System.out.println("Token格式错误: " + e.getMessage());
            return false;
        } catch (SignatureException e) {
            System.out.println("签名验证失败: " + e.getMessage());
            return false;
        } catch (Exception e) {
            System.out.println("Token验证失败: " + e.getMessage());
            return false;
        }
    }

    /**
     * 从Token中获取用户名
     * @param token
     * @return
     */
    public static String getUsernameFromToken(String token) {
        try {
            Claims claims = parseJWT(token);
            return claims.getSubject();
        } catch (Exception e) {
            return null;
        }
    }
}